﻿using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Text;
using System.Timers;
using System.Collections;

namespace KoDService
{
    [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
    public class KoDService : IKoDService
    {
        public static List<string> authenticated = new List<string>();
        public static Dictionary<string, DateTime> verificationCodes = new Dictionary<string, DateTime>();
        public Database DB = new Database();
        Timer verificationTimer = new Timer(3600000);

        public KoDService()
        {
            verificationTimer.Elapsed += verificationTimer_Elapsed;
        }

        void verificationTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            foreach (var item in verificationCodes)
            {
                if ((DateTime.Now - item.Value).TotalHours > 1)
                    verificationCodes.Remove(item.Key);
            }
        }

        public bool ResendVerificationCode(string email)
        {
            if (verificationCodes.Count > 83)
                return false;
            string verCode = Guid.NewGuid().ToString();
            while (verificationCodes.ContainsKey(verCode))
            {
                verCode = Guid.NewGuid().ToString();
            }
            verificationCodes.Add(verCode, DateTime.Now);
            MailAddress fromAddress = new MailAddress("email.kingdom.of.death@gmail.com", "Kingdom of Death");
            MailAddress toAddress = new MailAddress(email);
            const string fromPassword = "ssxmeaqogdbpdrri";
            const string subject = "Verification - Resent";
            string body = "DO NOT REPLY TO THIS EMAIL\n\nHi, welcome to Kingdom of Death, to get going you have to verify your account, to do this use the below verification code to veryfy your account.\n\nVerification Code: " + verCode + "\n\nType or Copy the code into the client.";

            SmtpClient smtp = new SmtpClient
            {
                Host = "smtp.gmail.com",
                Port = 587,
                EnableSsl = true,
                DeliveryMethod = SmtpDeliveryMethod.Network,
                UseDefaultCredentials = false,
                Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
            };
            using (MailMessage message = new MailMessage(fromAddress, toAddress)
            {
                Subject = subject,
                Body = body
            })
            {
                smtp.Send(message);
            }
            return true;
        }

        public bool CheckUserNameInUse(string name)
        {
            try
            {
                DB.openDB();
                MySqlDataReader dbReader = DB.ExecuteQuery("SELECT COUNT(PlayerName) AS Exists FROM Player WHERE PlayerName='" + name + "';");
                if (dbReader.Read())
                    if (Convert.ToInt32(dbReader["Exists"]) == 1)
                    {
                        dbReader.Close();
                        DB.closeDB();
                        return true;
                    }
                dbReader.Close();
                DB.closeDB();
            }
            catch (Exception)
            {
            }
            return false;
        }

        public bool CheckEmailUsed(string email)
        {
            try
            {
                DB.openDB();
                MySqlDataReader dbReader = DB.ExecuteQuery("SELECT COUNT(AccountEmail) AS Exists FROM Account WHERE AccountEmail='" + email + "';");
                if (dbReader.Read())
                    if (Convert.ToInt32(dbReader["Exists"]) > 0)
                    {
                        dbReader.Close();
                        DB.closeDB();
                        return true;
                    }
                dbReader.Close();
                DB.closeDB();
            }
            catch (Exception)
            {
            }
            return false;
        }

        public void Logout(string SessionID)
        {
            if (authenticated.Contains(SessionID))
                authenticated.Remove(SessionID);
        }

        public string Login(string email, string password)
        {
            try
            {
                string passwordHash = "";

                if (!DB.openDB())// test if can open db
                    return "4";
                MySqlDataReader dbReader = DB.ExecuteQuery("SELECT accountPassword, AccountVerified FROM account WHERE AccountEmail='" + email + "';");
                if (dbReader.Read())// test if the email exists
                {
                    passwordHash = dbReader["accountPassword"].ToString();// get password for email
                    if (!Convert.ToBoolean(dbReader["AccountVerified"]))
                    {
                        return "5";
                    }
                }
                else
                    return "1";
                dbReader.Close();
                DB.closeDB();
                if (password == GetHash(passwordHash))// check if password is correct.
                {
                    string SessionID = Guid.NewGuid().ToString();//create GUID
                    while (authenticated.Contains(SessionID))
                    {
                        SessionID = Guid.NewGuid().ToString();
                    }
                    authenticated.Add(SessionID);// add and return the GUID
                    return SessionID;
                }
                else
                    return "2";// pass incorect
            }
            catch (Exception)
            {
                return "3";// server error
            }
        }

        public bool CreateAccount(string email, string password, DateTime DoB, string name, string gender)
        {
            try
            {
                DB.openDB();
                DB.ExecuteQuery("INSERT INTO Account(AccountEmail, accountPassword, DateOfBirth, Gender, CreationTime) VALUES('" + email + "', '" + GetHash(password) + "', '" + DateToString(DoB) + "', '" + gender + "','" + DateToString(DateTime.Now) + "')");
                DB.ExecuteQuery("INSERT INTO Player(PlayerEmail, PlayerName) VALUES('" + email + "', '" + name + "')");
                DB.closeDB();
                string verCode = Guid.NewGuid().ToString();
                while (verificationCodes.ContainsKey(verCode))
                {
                    verCode = Guid.NewGuid().ToString();
                }
                verificationCodes.Add(verCode, DateTime.Now);
                
                MailAddress fromAddress = new MailAddress("email.kingdom.of.death@gmail.com", "Kingdom of Death");
                MailAddress toAddress = new MailAddress(email, name);
                const string fromPassword = "ssxmeaqogdbpdrri";
                const string subject = "Verification";
                string body = "DO NOT REPLY TO THIS EMAIL\n\nHi, welcome to Kingdom of Death, to get going you have to verify your account, to do this use the below verification code to veryfy your account.\n\nVerification Code: " + verCode + "\n\nType or Copy the code into the client.";

                SmtpClient smtp = new SmtpClient
                {
                    Host = "smtp.gmail.com",
                    Port = 587,
                    EnableSsl = true,
                    DeliveryMethod = SmtpDeliveryMethod.Network,
                    UseDefaultCredentials = false,
                    Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
                };
                using (MailMessage message = new MailMessage(fromAddress, toAddress)
                {
                    Subject = subject,
                    Body = body
                })
                {
                    smtp.Send(message);
                }
            }
            catch (Exception)
            {
                return false;
            }
            return true;
        }



        public string GetHash(string str)// create hash from string
        {
            byte[] bytes = Encoding.UTF8.GetBytes(str);
            MD5 md5Hasher = MD5.Create();
            bytes = md5Hasher.ComputeHash(bytes);
            StringBuilder result = new StringBuilder(bytes.Length * 2);
            for (int i = 0; i < bytes.Length; i++)
                result.Append(bytes[i].ToString("X2"));
            return result.ToString();
        }

        private string DateToString(DateTime dt)
        {
            return "STR_TO_DATE('" + dt.ToString("dd/mm/yyyy HH:mm:ss tt") + "', //'%d/%m/%Y %r')";
        }

        public double GetLatestVersion()
        {
            return 0.09;
        }
    }
}